package com.ruoyi.system.controller;

import java.awt.*;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import com.ruoyi.common.core.constant.ActivityConstant;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.SigninConstants;
import com.ruoyi.common.core.utils.Base64Utils;
import com.ruoyi.common.core.utils.QrUtils;
import com.ruoyi.common.core.utils.RegExUtil;
import com.ruoyi.common.core.utils.uuid.IdUtils;
import com.ruoyi.common.security.annotation.InnerAuth;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.common.utils.uuid.VerificationCode;
import com.ruoyi.system.api.RemoteOssService;
import com.ruoyi.system.domain.Activity;
import com.ruoyi.system.domain.vo.SigninVo;
import com.ruoyi.system.service.IActivityService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.SigninRule;
import com.ruoyi.system.service.ISigninRuleService;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;

/**
 * 签到规则Controller
 * 
 * @author hyb
 * @date 2023-02-13
 */

@Transactional(rollbackFor = Exception.class)
@RestController
@RequestMapping("/signupRule")
public class SigninRuleController extends BaseController
{
    @Autowired
    private ISigninRuleService signinRuleService;

    @Autowired
    private IActivityService activityService;


    @Autowired
    private RemoteOssService remoteOssService;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;
    /**
     * 查询签到规则列表
     */
    @RequiresPermissions("signupRule:signupRule:list")
    @GetMapping("/list")
    public TableDataInfo list(SigninRule signinRule)
    {
        //只能查到自己添加的
        signinRule.setPf2(String.valueOf(SecurityUtils.getUserId()));
        startPage();
        List<SigninRule> list = signinRuleService.selectSigninRuleList(signinRule);
        return getDataTable(list);
    }

    /**
     * 导出签到规则列表
     */
    @RequiresPermissions("signupRule:signupRule:export")
    @Log(title = "签到规则", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SigninRule signinRule)
    {
        List<SigninRule> list = signinRuleService.selectSigninRuleList(signinRule);
        ExcelUtil<SigninRule> util = new ExcelUtil<SigninRule>(SigninRule.class);
        util.exportExcel(response, list, "签到规则数据");
    }

    /**
     * 获取签到规则详细信息
     */
    @RequiresPermissions("signupRule:signupRule:query")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return success(signinRuleService.selectSigninRuleById(id));
    }

    /*
    * 返回签到规则
    * */
    @InnerAuth
    @GetMapping("/getActivityInfo")
    public AjaxResult getCheckInfo(@RequestParam("id")String id,@RequestParam("type")Long type){
        if (!RegExUtil.isNumber(id)){
            return AjaxResult.error("id必须是数字");
        }
        SigninRule signinRule = new SigninRule();
        signinRule.setActivityId(Long.parseLong(id));
        signinRule.setType(type);
        List<SigninRule> signinRules = signinRuleService.selectSigninRuleList(signinRule);
        if (signinRules.size()==0){
            return AjaxResult.error();
        }
        return AjaxResult.success().put(SigninConstants.NAME, signinRules.get(0));
    }

    /**
     * 新增签到规则
     */
    @RequiresPermissions("signupRule:signupRule:add")
    @Log(title = "签到规则", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SigninRule signinRule) throws Exception {
        //只有负责人才能新增签到规则
        Long activityId = signinRule.getActivityId();
        Activity activity = activityService.selectActivityById(activityId);
        if (activity==null){
            return AjaxResult.error("活动不存在");
        }

        if (!SecurityUtils.getUserId().equals(activity.getUserId())){
            return AjaxResult.error("只有负责人能新增签到规则");
        }

        if (!activity.getStatus().equals(ActivityConstant.STARTING_STATUS)){
            return AjaxResult.error("活动未进行中,无法新增签到规规则");
        }
        String url ="";
        String letter ="";
        String fileName="";
        long l=signinRule.getTimeLong()*60*1000;
        if (signinRule.getType().equals(SigninConstants.QRCODE_TYPE)){
            //生成二维码并保存到
            //生成一个随机码,这个随机码保存到redis里
            //将上传的业务逻辑放到mq里,加快返回速度,提升用户体验
            String s = IdUtils.simpleUUID();
            //计算过期时间
            String encryptPassword = SecurityUtils.encryptPassword(s);

            redisTemplate.opsForValue().set(SigninConstants.QRCODE_RULE_KEY+activityId,encryptPassword,l, TimeUnit.MILLISECONDS);

            String in = QrUtils.crateQRCode(activityId+":"+s, 300, 300);
            Map<String,Object> map=new HashMap<>();
            map.put("activityId",activityId);
            map.put("in",in);
            map.put("signinRule",signinRule);
            map.put("f",true);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String format = simpleDateFormat.format(new Date());
            fileName=format+IdUtils.fastUUID()+".png";
            map.put("fileName",fileName);
            rabbitTemplate.convertAndSend("topicExchange","topic.sign.sign",map);
            url = in;
            signinRule.setPf1(url);
        }else{
            //生成随机码并保存
            letter = VerificationCode.getLetter(6);
            //设置过期时间
            String letters = SecurityUtils.encryptPassword(letter);
            redisTemplate.opsForValue().set(SigninConstants.PASSWORD_RULE_KEY+activityId,letters,l, TimeUnit.MILLISECONDS);
            signinRule.setPf1(letters);
            Map<String,Object> map=new HashMap<>();
            map.put("activityId",activityId);
            map.put("signinRule",signinRule);
            map.put("f",false);
            rabbitTemplate.convertAndSend("topicExchange","topic.sign.sign",map);

        }
        Map<String,String> map=new HashMap<>();
        map.put("url",url);
        map.put("code",letter);
        map.put("fileName",fileName);

        //缓存地点
        redisTemplate.opsForValue().set(SigninConstants.POSITION_LONG+activityId,String.valueOf(signinRule.getPositionLong()),l,TimeUnit.MILLISECONDS);

        return AjaxResult.success().put("map",map);
    }

    /*
    * 下载二维码
    * */
    @RequiresPermissions("signupRule:signupRule:down")
    @GetMapping("/download")
    public AjaxResult download(@RequestParam("path")String path,@RequestParam("fileName")String fileName){

        AjaxResult ajaxResult = remoteOssService.downLoad(path,fileName, SecurityConstants.INNER);
        if (ajaxResult.isError()){
            return AjaxResult.error("未知异常");
        }
        return AjaxResult.success();

    }

    /**
     * 修改签到规则
     */
    @RequiresPermissions("signupRule:signupRule:edit")
    @Log(title = "签到规则", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SigninRule signinRule)
    {
        return toAjax(signinRuleService.updateSigninRule(signinRule));
    }

    /**
     * 删除签到规则
     */
    @RequiresPermissions("signupRule:signupRule:remove")
    @Log(title = "签到规则", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(signinRuleService.deleteSigninRuleByIds(ids));
    }
}
